﻿using PPSkin.Enums;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace PPSkin
{
    public static class PaintHelper
    {
        /// <summary>
        /// 设置GDI高质量模式抗锯齿
        /// </summary>
        /// <param name="g"></param>
        public static void SetGraphicsHighQuality(Graphics g)
        {
            g.SmoothingMode = SmoothingMode.AntiAlias;  //使绘图质量最高，即消除锯齿
            //g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            //g.CompositingQuality = CompositingQuality.HighQuality;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
        }

        /// <summary>
        /// 设置GDI默认值
        /// </summary>
        /// <param name="g"></param>
        public static void SetGraphicsDefaultQuality(Graphics g)
        {
            g.SmoothingMode = SmoothingMode.Default;
            g.InterpolationMode = InterpolationMode.Default;
            g.CompositingQuality = CompositingQuality.Default;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SystemDefault;
        }

        // <summary>
        /// 建立带有圆角样式的路径。
        /// </summary>
        /// <param name="rect">用来建立路径的矩形。</param>
        /// <param name="_radius">圆角的大小。</param>
        /// <param name="style">圆角的样式。</param>
        /// <param name="correction">是否把矩形长宽减 1,以便画出边框。</param>
        /// <returns>建立的路径。</returns>
        public static GraphicsPath CreatePath(Rectangle rect, int radius, RoundStyle style=RoundStyle.All, bool correction=true)
        {
            GraphicsPath path = new GraphicsPath();
            int radiusCorrection = correction ? 1 : 0;
            if(radius<=0)
                style = RoundStyle.None;
            switch (style)
            {
                case RoundStyle.None:
                    path.AddRectangle(new Rectangle(rect.X,rect.Y,rect.Width-radiusCorrection,rect.Height-radiusCorrection));
                    break;
                case RoundStyle.All:
                    path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);
                    path.AddArc(
                        rect.Right - radius - radiusCorrection,
                        rect.Y,
                        radius,
                        radius,
                        270,
                        90);
                    path.AddArc(
                        rect.Right - radius - radiusCorrection,
                        rect.Bottom - radius - radiusCorrection,
                        radius,
                        radius, 0, 90);
                    path.AddArc(
                        rect.X,
                        rect.Bottom - radius - radiusCorrection,
                        radius,
                        radius,
                        90,
                        90);
                    break;
                case RoundStyle.Left:
                    path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);
                    path.AddLine(
                        rect.Right - radiusCorrection, rect.Y,
                        rect.Right - radiusCorrection, rect.Bottom - radiusCorrection);
                    path.AddArc(
                        rect.X,
                        rect.Bottom - radius - radiusCorrection,
                        radius,
                        radius,
                        90,
                        90);
                    break;
                case RoundStyle.Right:
                    path.AddArc(
                        rect.Right - radius - radiusCorrection,
                        rect.Y,
                        radius,
                        radius,
                        270,
                        90);
                    path.AddArc(
                       rect.Right - radius - radiusCorrection,
                       rect.Bottom - radius - radiusCorrection,
                       radius,
                       radius,
                       0,
                       90);
                    path.AddLine(rect.X, rect.Bottom - radiusCorrection, rect.X, rect.Y);
                    break;
                case RoundStyle.Top:
                    path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);
                    path.AddArc(
                        rect.Right - radius - radiusCorrection,
                        rect.Y,
                        radius,
                        radius,
                        270,
                        90);
                    path.AddLine(
                        rect.Right - radiusCorrection, rect.Bottom - radiusCorrection,
                        rect.X, rect.Bottom - radiusCorrection);
                    break;
                case RoundStyle.Bottom:
                    path.AddArc(
                        rect.Right - radius - radiusCorrection,
                        rect.Bottom - radius - radiusCorrection,
                        radius,
                        radius,
                        0,
                        90);
                    path.AddArc(
                        rect.X,
                        rect.Bottom - radius - radiusCorrection,
                        radius,
                        radius,
                        90,
                        90);
                    path.AddLine(rect.X, rect.Y, rect.Right - radiusCorrection, rect.Y);
                    break;
                case RoundStyle.BottomLeft:
                    path.AddArc(
                        rect.X,
                        rect.Bottom - radius - radiusCorrection,
                        radius,
                        radius,
                        90,
                        90);
                    path.AddLine(rect.X, rect.Y, rect.Right - radiusCorrection, rect.Y);
                    path.AddLine(
                        rect.Right - radiusCorrection,
                        rect.Y,
                        rect.Right - radiusCorrection,
                        rect.Bottom - radiusCorrection);
                    break;
                case RoundStyle.BottomRight:
                    path.AddArc(
                        rect.Right - radius - radiusCorrection,
                        rect.Bottom - radius - radiusCorrection,
                        radius,
                        radius,
                        0,
                        90);
                    path.AddLine(rect.X, rect.Bottom - radiusCorrection, rect.X, rect.Y);
                    path.AddLine(rect.X, rect.Y, rect.Right - radiusCorrection, rect.Y);
                    break;

                case RoundStyle.TopLeft:
                    path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);
                    path.AddLine(
                        rect.Right - radiusCorrection,
                        rect.Y,
                        rect.Right - radiusCorrection,
                        rect.Bottom - radiusCorrection);
                    path.AddLine(
                        rect.Right - radiusCorrection, rect.Bottom - radiusCorrection,
                        rect.X, rect.Bottom - radiusCorrection);
                    break;
                case RoundStyle.TopRight:
                    path.AddArc(
                        rect.Right - radius - radiusCorrection,
                        rect.Y,
                        radius,
                        radius,
                        270,
                        90);
                    path.AddLine(
                        rect.Right - radiusCorrection, rect.Bottom - radiusCorrection,
                        rect.X, rect.Bottom - radiusCorrection);
                    path.AddLine(rect.X, rect.Bottom - radiusCorrection, rect.X, rect.Y);
                    break;
            }
            path.CloseFigure();
            return path;
        }

        // <summary>
        /// 建立带有圆角样式的路径。
        /// </summary>
        /// <param name="rect">用来建立路径的矩形。</param>
        /// <param name="_radius">圆角的大小。</param>
        /// <param name="style">圆角的样式。</param>
        /// <param name="correction">是否把矩形长宽减 1,以便画出边框。</param>
        /// <returns>建立的路径。</returns>
        public static GraphicsPath CreatePath(RectangleF rect, float radius, RoundStyle style = RoundStyle.All, bool correction = true)
        {
            GraphicsPath path = new GraphicsPath();
            int radiusCorrection = correction ? 1 : 0;
            if (radius <= 0)
                style = RoundStyle.None;
            switch (style)
            {
                case RoundStyle.None:
                    path.AddRectangle(new RectangleF(rect.X, rect.Y, rect.Width - radiusCorrection, rect.Height - radiusCorrection));
                    break;
                case RoundStyle.All:
                    path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);
                    path.AddArc(
                        rect.Right - radius - radiusCorrection,
                        rect.Y,
                        radius,
                        radius,
                        270,
                        90);
                    path.AddArc(
                        rect.Right - radius - radiusCorrection,
                        rect.Bottom - radius - radiusCorrection,
                        radius,
                        radius, 0, 90);
                    path.AddArc(
                        rect.X,
                        rect.Bottom - radius - radiusCorrection,
                        radius,
                        radius,
                        90,
                        90);
                    break;
                case RoundStyle.Left:
                    path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);
                    path.AddLine(
                        rect.Right - radiusCorrection, rect.Y,
                        rect.Right - radiusCorrection, rect.Bottom - radiusCorrection);
                    path.AddArc(
                        rect.X,
                        rect.Bottom - radius - radiusCorrection,
                        radius,
                        radius,
                        90,
                        90);
                    break;
                case RoundStyle.Right:
                    path.AddArc(
                        rect.Right - radius - radiusCorrection,
                        rect.Y,
                        radius,
                        radius,
                        270,
                        90);
                    path.AddArc(
                       rect.Right - radius - radiusCorrection,
                       rect.Bottom - radius - radiusCorrection,
                       radius,
                       radius,
                       0,
                       90);
                    path.AddLine(rect.X, rect.Bottom - radiusCorrection, rect.X, rect.Y);
                    break;
                case RoundStyle.Top:
                    path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);
                    path.AddArc(
                        rect.Right - radius - radiusCorrection,
                        rect.Y,
                        radius,
                        radius,
                        270,
                        90);
                    path.AddLine(
                        rect.Right - radiusCorrection, rect.Bottom - radiusCorrection,
                        rect.X, rect.Bottom - radiusCorrection);
                    break;
                case RoundStyle.Bottom:
                    path.AddArc(
                        rect.Right - radius - radiusCorrection,
                        rect.Bottom - radius - radiusCorrection,
                        radius,
                        radius,
                        0,
                        90);
                    path.AddArc(
                        rect.X,
                        rect.Bottom - radius - radiusCorrection,
                        radius,
                        radius,
                        90,
                        90);
                    path.AddLine(rect.X, rect.Y, rect.Right - radiusCorrection, rect.Y);
                    break;
                case RoundStyle.BottomLeft:
                    path.AddArc(
                        rect.X,
                        rect.Bottom - radius - radiusCorrection,
                        radius,
                        radius,
                        90,
                        90);
                    path.AddLine(rect.X, rect.Y, rect.Right - radiusCorrection, rect.Y);
                    path.AddLine(
                        rect.Right - radiusCorrection,
                        rect.Y,
                        rect.Right - radiusCorrection,
                        rect.Bottom - radiusCorrection);
                    break;
                case RoundStyle.BottomRight:
                    path.AddArc(
                        rect.Right - radius - radiusCorrection,
                        rect.Bottom - radius - radiusCorrection,
                        radius,
                        radius,
                        0,
                        90);
                    path.AddLine(rect.X, rect.Bottom - radiusCorrection, rect.X, rect.Y);
                    path.AddLine(rect.X, rect.Y, rect.Right - radiusCorrection, rect.Y);
                    break;

                case RoundStyle.TopLeft:
                    path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);
                    path.AddLine(
                        rect.Right - radiusCorrection,
                        rect.Y,
                        rect.Right - radiusCorrection,
                        rect.Bottom - radiusCorrection);
                    path.AddLine(
                        rect.Right - radiusCorrection, rect.Bottom - radiusCorrection,
                        rect.X, rect.Bottom - radiusCorrection);
                    break;
                case RoundStyle.TopRight:
                    path.AddArc(
                        rect.Right - radius - radiusCorrection,
                        rect.Y,
                        radius,
                        radius,
                        270,
                        90);
                    path.AddLine(
                        rect.Right - radiusCorrection, rect.Bottom - radiusCorrection,
                        rect.X, rect.Bottom - radiusCorrection);
                    path.AddLine(rect.X, rect.Bottom - radiusCorrection, rect.X, rect.Y);
                    break;
                
            }
            path.CloseFigure();
            return path;
        }


        /// <summary>
        /// 获取文本在矩形框中的居中位置
        /// </summary>
        /// <param name="text"></param>
        /// <param name="font"></param>
        /// <param name="rect"></param>
        /// <returns></returns>
        public static RectangleF GetTextCenterInRect(string text, Font font, RectangleF rect)
        {
            //Bitmap bmp = new Bitmap((int)rect.Width, (int)rect.Height);
            //Graphics g = Graphics.FromImage(bmp);
            SizeF fontsize = TextRenderer.MeasureText(text, font);

            PointF centerPoint = new PointF(rect.Left + (rect.Width - fontsize.Width) / 2, rect.Top + (rect.Height - fontsize.Height) / 2);

            //g.Dispose();
            //bmp.Dispose();

            return new RectangleF(centerPoint, fontsize);
        }

        /// <summary>
        /// 获取文本在矩形框中的位置
        /// </summary>
        /// <param name="text"></param>
        /// <param name="font"></param>
        /// <param name="rect"></param>
        /// <param name="textAlign"></param>
        /// <returns></returns>
        public static RectangleF GetTextRectInRect(string text, Font font, RectangleF rect, ContentAlignment textAlign)
        {
            Bitmap bmp = new Bitmap((int)rect.Width, (int)rect.Height);
            Graphics g = Graphics.FromImage(bmp);
            SizeF fontsize = g.MeasureString(text, font);
            PointF textPoint = new PointF(rect.Left + (rect.Width - fontsize.Width) / 2, rect.Top + (rect.Height - fontsize.Height) / 2); ;
            switch (textAlign)
            {
                case ContentAlignment.MiddleLeft: textPoint = new PointF(rect.Left, rect.Top + (rect.Height - fontsize.Height) / 2); break;
                case ContentAlignment.MiddleRight: textPoint = new PointF(rect.Left + (rect.Width - fontsize.Width), rect.Top + (rect.Height - fontsize.Height) / 2); break;
                case ContentAlignment.MiddleCenter: textPoint = new PointF(rect.Left + (rect.Width - fontsize.Width) / 2, rect.Top + (rect.Height - fontsize.Height) / 2); break;
                case ContentAlignment.TopLeft: textPoint = new PointF(rect.Left, rect.Top); break;
                case ContentAlignment.TopRight: textPoint = new PointF(rect.Left + (rect.Width - fontsize.Width), rect.Top); break;
                case ContentAlignment.TopCenter: textPoint = new PointF(rect.Left + (rect.Width - fontsize.Width) / 2, rect.Top); break;
                case ContentAlignment.BottomLeft: textPoint = new PointF(rect.Left, rect.Top + (rect.Height - fontsize.Height)); break;
                case ContentAlignment.BottomRight: textPoint = new PointF(rect.Left + (rect.Width - fontsize.Width), rect.Top + (rect.Height - fontsize.Height)); break;
                case ContentAlignment.BottomCenter: textPoint = new PointF(rect.Left + (rect.Width - fontsize.Width) / 2, rect.Top + (rect.Height - fontsize.Height)); break;
            }

            return new RectangleF(textPoint, fontsize);
        }

        /// <summary>
        /// 获取文本对应字体的大小
        /// </summary>
        /// <param name="text"></param>
        /// <param name="font"></param>
        /// <param name="rect"></param>
        /// <returns></returns>
        public static SizeF GetTextSize(string text, Font font)
        {
            Bitmap bmp = new Bitmap(100, 100);
            Graphics g = Graphics.FromImage(bmp);
            SizeF fontsize = g.MeasureString(text, font);

            g.Dispose();
            bmp.Dispose();

            return fontsize;
        }

        /// <summary>
        /// 获取一个固定大小矩形在一个矩形中心的Rect
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        public static RectangleF GetCenterRectInRect(RectangleF rect, SizeF size)
        {
            PointF centerPoint = new PointF(rect.Left + (rect.Width - size.Width) / 2, rect.Top + (rect.Height - size.Height) / 2);
            return new RectangleF(centerPoint, size);
        }

        /// <summary>
        /// 获取矩形的中心点
        /// </summary>
        /// <param name="rect"></param>
        /// <returns></returns>
        public static Point GetCenterPointInRect(Rectangle rect)
        {
            return new Point(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2);
        }

        /// <summary>
        /// 将图片转为圆形
        /// </summary>
        /// <param name="bmp"></param>
        /// <param name="transparentColor">要转为圆形周围的透明颜色，确保图片中没有此颜色</param>
        /// <returns></returns>
        public static Bitmap GetRoundBmp(Bitmap bmp, Color transparentColor)
        {
            Bitmap bitmap = bmp.Clone() as Bitmap;
            Graphics g = Graphics.FromImage(bitmap);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            GraphicsPath path = new GraphicsPath();
            path.AddEllipse(new Rectangle(0, 0, bitmap.Width - 1, bitmap.Height - 1));
            path.AddRectangle(new Rectangle(-1, -1, bitmap.Width + 1, bitmap.Height + 1));
            SolidBrush solidBrush = new SolidBrush(transparentColor);
            g.FillPath(solidBrush, path);
            bitmap.MakeTransparent(transparentColor);
            path.Dispose();
            g.Dispose();
            solidBrush.Dispose();
            return bitmap;
        }

        /// <summary>
        /// 剪切图片为正方形，以最短的边长为边长，位置居中
        /// </summary>
        /// <param name="bmp"></param>
        /// <returns></returns>
        public static Bitmap CutBmpToSquare(Bitmap bmp)
        {
            Rectangle rectangle;
            if (bmp.Width > bmp.Height)
            {
                rectangle = new Rectangle((bmp.Width - bmp.Height) / 2, 0, bmp.Height, bmp.Height);
            }
            else if (bmp.Width < bmp.Height)
            {
                rectangle = new Rectangle(0, (bmp.Height - bmp.Width) / 2, bmp.Width, bmp.Width);
            }
            else
            {
                return bmp;
            }

            return bmp.Clone(rectangle, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
        }

        /// <summary>
        /// 图片放大镜，将图片像素放大显示其像素位图
        /// </summary>
        /// <param name="srcbitmap">源图片</param>
        /// <param name="multiple">放大倍数</param>
        /// <returns></returns>
        public static Bitmap BitmapMagnifier(Bitmap srcbitmap, int multiple)
        {
            if (multiple <= 0) { multiple = 0; return srcbitmap; }
            Bitmap bitmap = new Bitmap(srcbitmap.Size.Width * multiple, srcbitmap.Size.Height * multiple);
            BitmapData srcbitmapdata = srcbitmap.LockBits(new Rectangle(new Point(0, 0), srcbitmap.Size), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            BitmapData bitmapdata = bitmap.LockBits(new Rectangle(new Point(0, 0), bitmap.Size), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            unsafe
            {
                byte* srcbyte = (byte*)(srcbitmapdata.Scan0.ToPointer());
                byte* sourcebyte = (byte*)(bitmapdata.Scan0.ToPointer());
                for (int y = 0; y < bitmapdata.Height; y++)
                {
                    for (int x = 0; x < bitmapdata.Width; x++)
                    {
                        long index = (x / multiple) * 4 + (y / multiple) * srcbitmapdata.Stride;
                        sourcebyte[0] = srcbyte[index];
                        sourcebyte[1] = srcbyte[index + 1];
                        sourcebyte[2] = srcbyte[index + 2];
                        sourcebyte[3] = srcbyte[index + 3];
                        sourcebyte += 4;
                    }
                }
            }
            srcbitmap.UnlockBits(srcbitmapdata);
            bitmap.UnlockBits(bitmapdata);
            return bitmap;
        }
    }
}